home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 23 / Amiga Format AFCD23 (Feb 1998, Issue 107).iso / -in_the_mag- / emulation / consoles / amigavgb / debug.c < prev    next >
C/C++ Source or Header  |  1997-12-12  |  13KB  |  317 lines

  1. /** VGB: portable GameBoy emulator ***************************/
  2. /**                                                         **/
  3. /**                         Debug.c                         **/
  4. /**                                                         **/
  5. /** This file contains the built-in debugging routine for   **/
  6. /** the GameBoy emulator which is called on each CPU step   **/
  7. /** when Trap==TRUE.                                        **/
  8. /**                                                         **/
  9. /** Copyright (C) Marat Fayzullin 1995,1996                 **/
  10. /**               Pascal Felber   1996                      **/
  11. /**     You are not allowed to distribute this software     **/
  12. /**     commercially. Please, notify me, if you make any    **/
  13. /**     changes to this file.                               **/
  14. /*************************************************************/
  15.  
  16. #ifdef DEBUG
  17.  
  18. #include "Z80.h"
  19. #include <stdio.h>
  20. #include <string.h>
  21.  
  22. int DAsm(char *S,word A);
  23.  
  24. char *Mnemonics[256] =
  25. {
  26.   "NOP","LD BC,#h","LD (BC),A","INC BC","INC B","DEC B","LD B,*h","RLCA",
  27.   "LD (#h),SP","ADD HL,BC","LD A,(BC)","DEC BC","INC C","DEC C","LD C,*h","RRCA",
  28.   "STOP","LD DE,#h","LD (DE),A","INC DE","INC D","DEC D","LD D,*h","RLA",
  29.   "JR @h","ADD HL,DE","LD A,(DE)","DEC DE","INC E","DEC E","LD E,*h","RRA",
  30.   "JR NZ,@h","LD HL,#h","LD (HL+),A","INC HL","INC H","DEC H","LD H,*h","DAA",
  31.   "JR Z,@h","ADD HL,HL","LD A,(HL+)","DEC HL","INC L","DEC L","LD L,*h","CPL",
  32.   "JR NC,@h","LD SP,#h","LD (HL-),A","INC SP","INC (HL)","DEC (HL)","LD (HL),*h","SCF",
  33.   "JR C,@h","ADD HL,SP","LD A,(HL-)","DEC SP","INC A","DEC A","LD A,*h","CCF",
  34.   "LD B,B","LD B,C","LD B,D","LD B,E","LD B,H","LD B,L","LD B,(HL)","LD B,A",
  35.   "LD C,B","LD C,C","LD C,D","LD C,E","LD C,H","LD C,L","LD C,(HL)","LD C,A",
  36.   "LD D,B","LD D,C","LD D,D","LD D,E","LD D,H","LD D,L","LD D,(HL)","LD D,A",
  37.   "LD E,B","LD E,C","LD E,D","LD E,E","LD E,H","LD E,L","LD E,(HL)","LD E,A",
  38.   "LD H,B","LD H,C","LD H,D","LD H,E","LD H,H","LD H,L","LD H,(HL)","LD H,A",
  39.   "LD L,B","LD L,C","LD L,D","LD L,E","LD L,H","LD L,L","LD L,(HL)","LD L,A",
  40.   "LD (HL),B","LD (HL),C","LD (HL),D","LD (HL),E","LD (HL),H","LD (HL),L","HALT","LD (HL),A",
  41.   "LD A,B","LD A,C","LD A,D","LD A,E","LD A,H","LD A,L","LD A,(HL)","LD A,A",
  42.   "ADD B","ADD C","ADD D","ADD E","ADD H","ADD L","ADD (HL)","ADD A",
  43.   "ADC B","ADC C","ADC D","ADC E","ADC H","ADC L","ADC (HL)","ADC A",
  44.   "SUB B","SUB C","SUB D","SUB E","SUB H","SUB L","SUB (HL)","SUB A",
  45.   "SBC B","SBC C","SBC D","SBC E","SBC H","SBC L","SBC (HL)","SBC A",
  46.   "AND B","AND C","AND D","AND E","AND H","AND L","AND (HL)","AND A",
  47.   "XOR B","XOR C","XOR D","XOR E","XOR H","XOR L","XOR (HL)","XOR A",
  48.   "OR B","OR C","OR D","OR E","OR H","OR L","OR (HL)","OR A",
  49.   "CP B","CP C","CP D","CP E","CP H","CP L","CP (HL)","CP A",
  50.   "RET NZ","POP BC","JP NZ,#h","JP #h","CALL NZ,#h","PUSH BC","ADD *h","RST 00h",
  51.   "RET Z","RET","JP Z,#h","PREFIX CBh","CALL Z,#h","CALL #h","ADC *h","RST 08h",
  52.   "RET NC","POP DE","JP NC,#h","DB D3h","CALL NC,#h","PUSH DE","SUB *h","RST 10h",
  53.   "RET C","RETI","JP C,#h","DB DBh","CALL C,#h","DB DDh","SBC *h","RST 18h",
  54.   "LD (FF*h),A","POP HL","LD (FF00h+C),A","EX HL,(SP)","DB E4h","PUSH HL","AND *h","RST 20h",
  55.   "ADD SP,@h","LD PC,HL","LD (#h),A","DB EBh","DB ECh","PREFIX EDh","XOR *h","RST 28h",
  56.   "LD A,(FF*h)","POP AF","LD A,(FF00h+C)","DI","DB F4h","PUSH AF","OR *h","RST 30h",
  57.   "LDHL SP,@h","LD SP,HL","LD A,(#h)","EI","DB FCh","DB FDh","CP *h","RST 38h"
  58. };
  59.  
  60. char *MnemonicsCB[256] =
  61. {
  62.   "RLC B","RLC C","RLC D","RLC E","RLC H","RLC L","RLC (HL)","RLC A",
  63.   "RRC B","RRC C","RRC D","RRC E","RRC H","RRC L","RRC (HL)","RRC A",
  64.   "RL B","RL C","RL D","RL E","RL H","RL L","RL (HL)","RL A",
  65.   "RR B","RR C","RR D","RR E","RR H","RR L","RR (HL)","RR A",
  66.   "SLA B","SLA C","SLA D","SLA E","SLA H","SLA L","SLA (HL)","SLA A",
  67.   "SRA B","SRA C","SRA D","SRA E","SRA H","SRA L","SRA (HL)","SRA A",
  68.   "SWAP B","SWAP C","SWAP D","SWAP E","SWAP H","SWAP L","SWAP (HL)","SWAP A",
  69.   "SRL B","SRL C","SRL D","SRL E","SRL H","SRL L","SRL (HL)","SRL A",
  70.   "BIT 0,B","BIT 0,C","BIT 0,D","BIT 0,E","BIT 0,H","BIT 0,L","BIT 0,(HL)","BIT 0,A",
  71.   "BIT 1,B","BIT 1,C","BIT 1,D","BIT 1,E","BIT 1,H","BIT 1,L","BIT 1,(HL)","BIT 1,A",
  72.   "BIT 2,B","BIT 2,C","BIT 2,D","BIT 2,E","BIT 2,H","BIT 2,L","BIT 2,(HL)","BIT 2,A",
  73.   "BIT 3,B","BIT 3,C","BIT 3,D","BIT 3,E","BIT 3,H","BIT 3,L","BIT 3,(HL)","BIT 3,A",
  74.   "BIT 4,B","BIT 4,C","BIT 4,D","BIT 4,E","BIT 4,H","BIT 4,L","BIT 4,(HL)","BIT 4,A",
  75.   "BIT 5,B","BIT 5,C","BIT 5,D","BIT 5,E","BIT 5,H","BIT 5,L","BIT 5,(HL)","BIT 5,A",
  76.   "BIT 6,B","BIT 6,C","BIT 6,D","BIT 6,E","BIT 6,H","BIT 6,L","BIT 6,(HL)","BIT 6,A",
  77.   "BIT 7,B","BIT 7,C","BIT 7,D","BIT 7,E","BIT 7,H","BIT 7,L","BIT 7,(HL)","BIT 7,A",
  78.   "RES 0,B","RES 0,C","RES 0,D","RES 0,E","RES 0,H","RES 0,L","RES 0,(HL)","RES 0,A",
  79.   "RES 1,B","RES 1,C","RES 1,D","RES 1,E","RES 1,H","RES 1,L","RES 1,(HL)","RES 1,A",
  80.   "RES 2,B","RES 2,C","RES 2,D","RES 2,E","RES 2,H","RES 2,L","RES 2,(HL)","RES 2,A",
  81.   "RES 3,B","RES 3,C","RES 3,D","RES 3,E","RES 3,H","RES 3,L","RES 3,(HL)","RES 3,A",
  82.   "RES 4,B","RES 4,C","RES 4,D","RES 4,E","RES 4,H","RES 4,L","RES 4,(HL)","RES 4,A",
  83.   "RES 5,B","RES 5,C","RES 5,D","RES 5,E","RES 5,H","RES 5,L","RES 5,(HL)","RES 5,A",
  84.   "RES 6,B","RES 6,C","RES 6,D","RES 6,E","RES 6,H","RES 6,L","RES 6,(HL)","RES 6,A",
  85.   "RES 7,B","RES 7,C","RES 7,D","RES 7,E","RES 7,H","RES 7,L","RES 7,(HL)","RES 7,A",
  86.   "SET 0,B","SET 0,C","SET 0,D","SET 0,E","SET 0,H","SET 0,L","SET 0,(HL)","SET 0,A",
  87.   "SET 1,B","SET 1,C","SET 1,D","SET 1,E","SET 1,H","SET 1,L","SET 1,(HL)","SET 1,A",
  88.   "SET 2,B","SET 2,C","SET 2,D","SET 2,E","SET 2,H","SET 2,L","SET 2,(HL)","SET 2,A",
  89.   "SET 3,B","SET 3,C","SET 3,D","SET 3,E","SET 3,H","SET 3,L","SET 3,(HL)","SET 3,A",
  90.   "SET 4,B","SET 4,C","SET 4,D","SET 4,E","SET 4,H","SET 4,L","SET 4,(HL)","SET 4,A",
  91.   "SET 5,B","SET 5,C","SET 5,D","SET 5,E","SET 5,H","SET 5,L","SET 5,(HL)","SET 5,A",
  92.   "SET 6,B","SET 6,C","SET 6,D","SET 6,E","SET 6,H","SET 6,L","SET 6,(HL)","SET 6,A",
  93.   "SET 7,B","SET 7,C","SET 7,D","SET 7,E","SET 7,H","SET 7,L","SET 7,(HL)","SET 7,A"
  94. };
  95.  
  96. char *MnemonicsED[256] =
  97. {
  98.   "DB EDh,00h","DB EDh,01h","DB EDh,02h","DB EDh,03h",
  99.   "DB EDh,04h","DB EDh,05h","DB EDh,06h","DB EDh,07h",
  100.   "DB EDh,08h","DB EDh,09h","DB EDh,0Ah","DB EDh,0Bh",
  101.   "DB EDh,0Ch","DB EDh,0Dh","DB EDh,0Eh","DB EDh,0Fh",
  102.   "DB EDh,10h","DB EDh,11h","DB EDh,12h","DB EDh,13h",
  103.   "DB EDh,14h","DB EDh,15h","DB EDh,16h","DB EDh,17h",
  104.   "DB EDh,18h","DB EDh,19h","DB EDh,1Ah","DB EDh,1Bh",
  105.   "DB EDh,1Ch","DB EDh,1Dh","DB EDh,1Eh","DB EDh,1Fh",
  106.   "DB EDh,20h","DB EDh,21h","DB EDh,22h","DB EDh,23h",
  107.   "DB EDh,24h","DB EDh,25h","DB EDh,26h","DB EDh,27h",
  108.   "DB EDh,28h","DB EDh,29h","DB EDh,2Ah","DB EDh,2Bh",
  109.   "DB EDh,2Ch","DB EDh,2Dh","DB EDh,2Eh","DB EDh,2Fh",
  110.   "DB EDh,30h","DB EDh,31h","DB EDh,32h","DB EDh,33h",
  111.   "DB EDh,34h","DB EDh,35h","DB EDh,36h","DB EDh,37h",
  112.   "DB EDh,38h","DB EDh,39h","DB EDh,3Ah","DB EDh,3Bh",
  113.   "DB EDh,3Ch","DB EDh,3Dh","DB EDh,3Eh","DB EDh,3Fh",
  114.   "DB EDh,40h","DB EDh,41h","SBC HL,BC","LD (#h),BC",
  115.   "DB EDh,44h","RETN","IM 0","LD I,A",
  116.   "DB EDh,48h","DB EDh,49h","ADC HL,BC","LD BC,(#h)", 
  117.   "DB EDh,4Ch","RETI","DB EDh,4Eh","LD R,A",
  118.   "DB EDh,50h","DB EDh,51h","SBC HL,DE","LD (#h),DE", 
  119.   "DB EDh,54h","DB EDh,55h","IM 1","LD A,I",
  120.   "DB EDh,58h","DB EDh,59h","ADC HL,DE","LD DE,(#h)", 
  121.   "DB EDh,5Ch","DB EDh,5Dh","IM 2","LD A,R",
  122.   "DB EDh,60h","DB EDh,61h","SBC HL,HL","LD (#h),HL", 
  123.   "DB EDh,64h","DB EDh,65h","DB EDh,66h","RRD",
  124.   "DB EDh,68h","DB EDh,69h","ADC HL,HL","LD HL,(#h)", 
  125.   "DB EDh,6Ch","DB EDh,6Dh","DB EDh,6Eh","RLD",
  126.   "DB EDh,70h","DB EDh,71h","SBC HL,SP","LD (#h),SP", 
  127.   "DB EDh,74h","DB EDh,75h","DB EDh,76h","DB EDh,77h",
  128.   "DB EDh,78h","DB EDh,79h","ADC HL,SP","LD SP,(#h)", 
  129.   "DB EDh,7Ch","DB EDh,7Dh","DB EDh,7Eh","DB EDh,7Fh",
  130.   "DB EDh,80h","DB EDh,81h","DB EDh,82h","DB EDh,83h",
  131.   "DB EDh,84h","DB EDh,85h","DB EDh,86h","DB EDh,87h",
  132.   "DB EDh,88h","DB EDh,89h","DB EDh,8Ah","DB EDh,8Bh",
  133.   "DB EDh,8Ch","DB EDh,8Dh","DB EDh,8Eh","DB EDh,8Fh",
  134.   "DB EDh,90h","DB EDh,91h","DB EDh,92h","DB EDh,93h",
  135.   "DB EDh,94h","DB EDh,95h","DB EDh,96h","DB EDh,97h",
  136.   "DB EDh,98h","DB EDh,99h","DB EDh,9Ah","DB EDh,9Bh",
  137.   "DB EDh,9Ch","DB EDh,9Dh","DB EDh,9Eh","DB EDh,9Fh",
  138.   "LDI","CPI","DB EDh,A2h","DB EDh,A3h",
  139.   "DB EDh,A4h","DB EDh,A5h","DB EDh,A6h","DB EDh,A7h",
  140.   "LDD","CPD","DB EDh,AAh","DB EDh,ABh",
  141.   "DB EDh,ACh","DB EDh,ADh","DB EDh,AEh","DB EDh,AFh",
  142.   "LDIR","CPIR","DB EDh,B2h","DB EDh,B3h",
  143.   "DB EDh,B4h","DB EDh,B5h","DB EDh,B6h","DB EDh,B7h",
  144.   "LDDR","CPDR","DB EDh,BAh","DB EDh,BBh",
  145.   "DB EDh,BCh","DB EDh,BDh","DB EDh,BEh","DB EDh,BFh",
  146.   "DB EDh,C0h","DB EDh,C1h","DB EDh,C2h","DB EDh,C3h",
  147.   "DB EDh,C4h","DB EDh,C5h","DB EDh,C6h","DB EDh,C7h",
  148.   "DB EDh,C8h","DB EDh,C9h","DB EDh,CAh","DB EDh,CBh",
  149.   "DB EDh,CCh","DB EDh,CDh","DB EDh,CEh","DB EDh,CFh",
  150.   "DB EDh,D0h","DB EDh,D1h","DB EDh,D2h","DB EDh,D3h",
  151.   "DB EDh,D4h","DB EDh,D5h","DB EDh,D6h","DB EDh,D7h",
  152.   "DB EDh,D8h","DB EDh,D9h","DB EDh,DAh","DB EDh,DBh",
  153.   "DB EDh,DCh","DB EDh,DDh","DB EDh,DEh","DB EDh,DFh",
  154.   "DB EDh,E0h","DB EDh,E1h","DB EDh,E2h","DB EDh,E3h",
  155.   "DB EDh,E4h","DB EDh,E5h","DB EDh,E6h","DB EDh,E7h",
  156.   "DB EDh,E8h","DB EDh,E9h","DB EDh,EAh","DB EDh,EBh",
  157.   "DB EDh,ECh","DB EDh,EDh","DB EDh,EEh","DB EDh,EFh",
  158.   "DB EDh,F0h","DB EDh,F1h","DB EDh,F2h","DB EDh,F3h",
  159.   "DB EDh,F4h","DB EDh,F5h","DB EDh,F6h","DB EDh,F7h",
  160.   "DB EDh,F8h","DB EDh,F9h","DB EDh,FAh","DB EDh,FBh",
  161.   "DB EDh,FCh","DB EDh,FDh","DB EDh,FEh","DB EDh,FFh"
  162. };
  163.  
  164. int DAsm(char *S,word A)
  165. {
  166.   char R[128],H[10],C,*T,*P;
  167.   byte J,Offset;
  168.   word B;
  169.  
  170.   B=A;C='\0';J=0;
  171.  
  172.   switch(M_RDMEM(B))
  173.   {
  174.     case 0xCB: B++;T=MnemonicsCB[M_RDMEM(B++)];break;
  175.     case 0xED: B++;T=MnemonicsED[M_RDMEM(B++)];break;
  176.     default:   T=Mnemonics[M_RDMEM(B++)];
  177.   }
  178.  
  179.   if(P=strchr(T,'^'))
  180.   {
  181.     strncpy(R,T,P-T);R[P-T]='\0';
  182.     sprintf(H,"%02X",M_RDMEM(B++));
  183.     strcat(R,H);strcat(R,P+1);
  184.   }
  185.   else strcpy(R,T);
  186.   if(P=strchr(R,'%')) *P=C;
  187.  
  188.   if(P=strchr(R,'*'))
  189.   {
  190.     strncpy(S,R,P-R);S[P-R]='\0';
  191.     sprintf(H,"%02X",M_RDMEM(B++));
  192.     strcat(S,H);strcat(S,P+1);
  193.   }
  194.   else
  195.     if(P=strchr(R,'@'))
  196.     {
  197.       strncpy(S,R,P-R);S[P-R]='\0';
  198.       if(!J) Offset=M_RDMEM(B++);
  199.       strcat(S,Offset&0x80? "-":"+");
  200.       J=Offset&0x80? 256-Offset:Offset;
  201.       sprintf(H,"%02X",J);
  202.       strcat(S,H);strcat(S,P+1);
  203.     }
  204.     else
  205.       if(P=strchr(R,'#'))
  206.       {
  207.         strncpy(S,R,P-R);S[P-R]='\0';
  208.         sprintf(H,"%04X",M_RDMEM(B)+256*M_RDMEM(B+1));
  209.         strcat(S,H);strcat(S,P+1);
  210.         B+=2;
  211.       }
  212.       else strcpy(S,R);
  213.  
  214.   return(B-A);
  215. }
  216.  
  217. /*** Single-step debugger ****************************/
  218. /*** This function should exist if DEBUG is        ***/
  219. /*** #defined. When Trace=TRUE, it is called after ***/
  220. /*** each command executed by the CPU and given    ***/
  221. /*** address of the address space and the register ***/
  222. /*** file.                                         ***/
  223. /*****************************************************/
  224. void Debug(reg *R)
  225. {
  226.   static char Flags[8] = "SZ.H.PNC";
  227.   char S[128],T[10];
  228.   byte J,I;
  229.    
  230.   DAsm(S,R->PC.W);
  231.   for(J=0,I=R->AF.B.l;J<8;J++,I<<=1) T[J]=I&0x80? Flags[J]:'.';
  232.   T[8]='\0';
  233.   
  234.   printf
  235.   (
  236.     "AF:%04X HL:%04X DE:%04X BC:%04X PC:%04X SP:%04X\n",
  237.     R->AF.W,R->HL.W,R->DE.W,R->BC.W,R->PC.W,R->SP.W
  238.   );
  239.   printf
  240.   (
  241.     "AT PC: [%02X - %s]   AT SP: [%04X]   FLAGS: [%s]\n",
  242.     M_RDMEM(R->PC.W),S,M_RDMEM(R->SP.W)+256*M_RDMEM(R->SP.W+1),T
  243.   );
  244.   
  245.   while(1)
  246.   {
  247.     printf("\n[Command,'?']-> ");
  248.     fflush(stdout);fflush(stdin);
  249.  
  250.     fgets(S,50,stdin);
  251.     for(J=0;S[J]>=' ';J++)
  252.       S[J]=toupper(S[J]);
  253.     S[J]='\0';
  254.  
  255.     switch(S[0])
  256.     {
  257.       case 'H':
  258.       case '?':
  259.         puts("\n<CR>       : break at next instruction");
  260.         puts("=<addr>    : break at addr");
  261.         puts("+<offset>  : break at PC + offset");
  262.         puts("c          : continue without break");
  263.         puts("m<addr>    : memory dump at addr");
  264.         puts("d<addr>    : disassembly at addr");
  265.         puts("?,h        : show this help text");
  266.         puts("q          : exit VGB");
  267.         break;
  268.  
  269.       case '\0': return;
  270.       case '=':  if(strlen(S)<2) break;
  271.                  else
  272.                  { sscanf(S+1,"%hX",&Trap);Trace=0;return; }
  273.       case '+':  if(strlen(S)<2) break;
  274.                  else
  275.                  { sscanf(S+1,"%hX",&Trap);Trap+=R->PC.W;Trace=0;return; }
  276.       case 'C':  Trap=0xFFFF;Trace=0;return; 
  277.       case 'Q':  CPURunning=Trace=0;return;
  278.  
  279.       case 'M':
  280.         {
  281.           word Addr;
  282.  
  283.           if(strlen(S)>1) sscanf(S+1,"%hX",&Addr); else Addr=R->PC.W;
  284.           puts("");
  285.           for(J=0;J<16;J++)
  286.           {
  287.             printf("%04X: ",Addr);
  288.             for(I=0;I<16;I++,Addr++)
  289.               printf("%02X ",M_RDMEM(Addr));
  290.             printf(" | ");Addr-=16;
  291.             for(I=0;I<16;I++,Addr++)
  292.               putchar(isprint(M_RDMEM(Addr))? M_RDMEM(Addr):'.');
  293.             puts("");
  294.           }
  295.         }
  296.         break;
  297.  
  298.       case 'D':
  299.         {
  300.           word Addr;
  301.  
  302.           if(strlen(S)>1) sscanf(S+1,"%hX",&Addr); else Addr=R->PC.W;
  303.           puts("");
  304.           for(J=0;J<16;J++)
  305.           {
  306.             printf("%04X: ",Addr);
  307.             Addr+=DAsm(S,Addr);
  308.             puts(S);
  309.           }
  310.         }
  311.         break;
  312.     }
  313.   }
  314. }
  315.  
  316. #endif
  317.